package ssi.peeno.ciphers;

import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;

import javax.crypto.*;
import javax.crypto.spec.*;

import org.bouncycastle.util.encoders.Base64;

public class SymCipher implements PeenoCipher, SymKeyGenerator {
	//TODO ma servirà dividere in blocchi anche qui? me sa di no...
	private SecretKey SKey;
	//private SecretKeySpec SKeySpec;
	private byte[] initVector = new byte[] { 0x10, 0x10, 0x01, 0x04, 0x01, 0x01, 0x01, 0x02,  0x10, 0x10, 0x01, 0x04, 0x01, 0x01, 0x01, 0x02 };
	private AlgorithmParameterSpec algParamSpec = new IvParameterSpec(initVector);
	private int sessionId=0;
	
	@Override
	public String crypt(String plaintext, Key key) throws Exception {
		byte[] cipherTextBytes = null;
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		cipher.init(Cipher.ENCRYPT_MODE, SKey, algParamSpec);
		cipherTextBytes = Base64.encode(cipher.doFinal(plaintext.getBytes()));
		String cipherText = new String(cipherTextBytes);
		return cipherText;
	}
	
	public String crypt(String plaintext) throws Exception{
		return crypt(plaintext, SKey);
	}
	
	@Override
	public String decrypt(String ciphertext, Key key) throws Exception {
		byte[] cipherTextBytes = Base64.decode(ciphertext.getBytes());
		byte[] plainTextBytes = null;
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		cipher.init(Cipher.DECRYPT_MODE, SKey, algParamSpec);
		plainTextBytes = cipher.doFinal(cipherTextBytes);
		String plainText = new String(plainTextBytes, "UTF8");
		return plainText;
	}
	
	public String decrypt(String ciphertext) throws Exception {
		return decrypt(ciphertext, SKey);
	}
	
	@Override
	public void generateKey() throws NoSuchAlgorithmException {
		SKey =  KeyGenerator.getInstance("AES").generateKey();	
	}
	
	public void setKey(String skey){
		
		this.SKey=SymCipher.stringToKey(skey);
		//sta cosa qua sotto non mi piace molto a sto punto mi potrei salva la key in byte[]? boh vedremo
		//byte[] raw = SKey.getEncoded();
		//SKeySpec = new SecretKeySpec(raw, "AES");
	}
	
	@Override
	public SecretKey getKey(){
		return SKey;
	}

	public void setKey(SecretKey sessionKey) {
		this.SKey=sessionKey;
	}
	
	public int getSessionId() {
		return sessionId;
	}
	
	public void setSessionId(int sessionId) {
		this.sessionId = sessionId;
	}
	
	//utility methods for session key
	public static SecretKey stringToKey(String key){
		return new SecretKeySpec(Base64.decode(key.getBytes()), "AES");
	}
	
	public static String keyToString(SecretKey key){
		return new String(Base64.encode(key.getEncoded()));
	}
}